#include "pch.hpp"
#include "ProjectWizard.hpp"

#include "Script.hpp"
#include "UiDefinition.hpp"
#include "Mesh.hpp"
#include "Material.hpp"

using namespace Engine;
using namespace Engine::Edit;




class ProjectTemplateModel
	: public QAbstractListModel
{
public:

	ProjectTemplateModel(QObject* parent, QList<ProjectTemplate> templates)
		: QAbstractListModel(parent)
		, m_templates(templates)
	{}

	virtual ~ProjectTemplateModel()
	{}

	virtual int rowCount(const QModelIndex& index = QModelIndex()) const
	{
		if(index.isValid())
			return 0;
		else
			return m_templates.size();
	}

	virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
	{
		const auto& templ = m_templates[index.row()];

		switch(role)
		{
		case Qt::DecorationRole:
			return templ.icon();
		case Qt::DisplayRole:
			return templ.name();
		default:
			return QVariant();
		}
	}

private:

	QList<ProjectTemplate>   m_templates;
};
///////////////////////////////////////////////////////////////////////////////////////////////////




ProjectWizard::ProjectWizard(QWidget* parent)
	: QDialog(parent)
{
	ui.setupUi(this);


	//
	// Create templates
	//

	// Empty project
	m_templates << ProjectTemplate(QPixmap(":/icons/application_form"),
		tr("Empty Project"),
		tr("This is a completely empty Project.\n"
		"Use this type of project if you want "
		"to start from scratch and know what you are doing"),
		[](QString name, QFileInfo fileName) -> Project::ptr { return Project::create(name, fileName); }
	);

	m_templates << ProjectTemplate(QPixmap(":/icons/application_form"),
		tr("Hello World!"),
		tr("This is the most basic project you can imagine.\n"
		"It displays the text 'Hello World!' in an ingame dialog."),
		[](QString name, QFileInfo fileName) -> Project::ptr
		{
			auto project = Project::create(name, fileName);

			auto script = Script::create("helloworld.as");
			QFile file(":/scripts/helloworld.as");
			verify(file.open(QIODevice::ReadOnly | QIODevice::Text)); //< It is important that we open the document in text mode to get windows line endings
			script->setContent(file.readAll());

			project->scripts()->add(script);
			return project;
		}
	);


	//
	// Project Template List View
	//

	ui.templateList->setModel(new ProjectTemplateModel(ui.templateList, m_templates));


	//
	// Slots
	//

	verify(connect(ui.templateList->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), SLOT(onTemplateSelected(const QModelIndex&))));
	verify(connect(ui.templateList, SIGNAL(activated(const QModelIndex&)), SLOT(onTemplateActivated(const QModelIndex&))));
	verify(connect(ui.nameEdit, SIGNAL(textChanged(const QString&)), SLOT(onNameChanged())));
	verify(connect(ui.locationEdit, SIGNAL(textChanged(const QString&)), SLOT(onLocationChanged())));
	verify(connect(ui.browseButton, SIGNAL(clicked()), SLOT(onBrowse())));
	verify(connect(this, SIGNAL(accepted()), SLOT(onAccept())));


	//
	// Final touch
	//

	ui.templateList->selectionModel()->select(ui.templateList->model()->index(0, 0), QItemSelectionModel::ClearAndSelect);
	ui.nameEdit->setText(tr("Unnamed"));
	ui.locationEdit->setText(QDir::currentPath());

	updateUi();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

ProjectWizard::~ProjectWizard()
{}
///////////////////////////////////////////////////////////////////////////////////////////////////




Project::ptr ProjectWizard::project() const
{
	return m_project;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void ProjectWizard::onTemplateSelected(const QModelIndex& index)
{
	auto t = templ(index);
	if(t == nullptr)
		return;

	ui.templateDescription->setText(t->description());
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectWizard::onTemplateActivated(const QModelIndex& index)
{
	// We'll try to accept (double click == shortcut for the lazy developer :P)
	if(!canAccept())
		return;

	auto t = templ(index);
	if(t == nullptr)
		return;

	accept();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectWizard::onNameChanged()
{
	updateUi();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectWizard::onLocationChanged()
{
	updateUi();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectWizard::onBrowse()
{
	// If the directory, entered by the user, is valid: It is selected
	// as the currently displayed directory for the selection dialog, otherwise
	// the current directory is used
	QDir dir = ui.locationEdit->text();
	QString current;
	if(dir.exists())
		current = dir.absolutePath();

	QString location = QFileDialog::getExistingDirectory(this, tr("Please select a directory"), current);
	if(!location.isEmpty())
		ui.locationEdit->setText(location);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void ProjectWizard::onAccept()
{
	auto index = ui.templateList->currentIndex();
	const auto t = templ(index);
	if(t == nullptr)
		return;

	QDir dir = ui.locationEdit->text();
	if(!dir.exists())
		return;

	m_project = t->create(ui.nameEdit->text(),
		dir.absoluteFilePath(ui.nameEdit->text()));
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void ProjectWizard::updateUi()
{
	ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(canAccept());
}
///////////////////////////////////////////////////////////////////////////////////////////////////

const ProjectTemplate* ProjectWizard::templ(const QModelIndex& index) const
{
	if(!index.isValid())
		return nullptr;

	if(index.row() >= m_templates.size())
		return nullptr;

	return &m_templates[index.row()];
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool ProjectWizard::canAccept() const
{
	QString name = ui.nameEdit->text();
	QDir    dir  = ui.locationEdit->text();

	return !name.isEmpty() && dir.exists();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
